/*
 *
 *      Copyright (c) 2018-2025, madp All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: 成都文思海辉金信软件有限公司
 *
 */

package com.pactera.madp.admin.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.lang.TypeReference;
import cn.hutool.http.HttpRequest;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.pactera.madp.admin.api.constant.UpmsConstant;
import com.pactera.madp.admin.api.dto.UserDTO;
import com.pactera.madp.admin.api.dto.UserInfo;
import com.pactera.madp.admin.api.dto.UserRoleDTO;
import com.pactera.madp.admin.api.dto.WxEmpDto;
import com.pactera.madp.admin.api.entity.SysDept;
import com.pactera.madp.admin.api.entity.SysRole;
import com.pactera.madp.admin.api.entity.SysUser;
import com.pactera.madp.admin.api.entity.SysWxDeptRelation;
import com.pactera.madp.admin.api.feign.RemoteWxService;
import com.pactera.madp.admin.api.vo.UserVO;
import com.pactera.madp.admin.api.vo.WxEmpVo;
import com.pactera.madp.admin.service.SysDeptService;
import com.pactera.madp.admin.service.SysRoleService;
import com.pactera.madp.admin.service.SysUserService;
import com.pactera.madp.admin.service.SysWxDeptRelationService;
import com.pactera.madp.common.core.constant.SecurityConstants;
import com.pactera.madp.common.core.exception.CheckedException;
import com.pactera.madp.common.core.util.DesensitizedUtils;
import com.pactera.madp.common.core.util.R;
import com.pactera.madp.common.log.annotation.SysLog;
import com.pactera.madp.common.security.annotation.Inner;
import com.pactera.madp.common.security.util.SecurityUtils;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiOperation;
import lombok.AllArgsConstructor;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.validation.Valid;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author madp
 * @date 2018/12/16
 */
@RestController
@AllArgsConstructor
@RequestMapping("/user")
@Api(value = "user", tags = "用户管理模块")
public class SysUserController {
	private final SysUserService userService;
	private final RemoteWxService remoteWxService;
	private final SysWxDeptRelationService relationService;
	private final SysRoleService roleService;
	private final SysDeptService sysDeptService;

	/**
	 * 获取当前用户全部信息
	 *
	 * @return 用户信息
	 */
	@GetMapping(value = {"/info"})
	public R info() {
		String username = SecurityUtils.getUser().getUsername();
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			return R.failed(null, "获取当前用户信息失败");
		}
		return R.ok(userService.findUserInfo(user));
	}

	/**
	 * 获取指定用户全部信息
	 *
	 * @return 用户信息
	 */
	@Inner
	@GetMapping("/info/{username}")
	public R info(@PathVariable String username) {
		SysUser user = userService.getOne(Wrappers.<SysUser>query()
				.lambda().eq(SysUser::getUsername, username));
		if (user == null) {
			// 为解决后管登录查询不到用户弹出认证框问题，这里直接返空
			return null;
			//return R.failed(null, String.format("用户信息为空 %s", username));
		}
		return R.ok(userService.findUserInfo(user));
	}

	/**
	 * 通过ID查询用户信息
	 *
	 * @param id ID
	 * @return 用户信息
	 */
	@GetMapping("/{id}")
	public R<UserVO> user(@PathVariable Integer id) {
		return R.ok(userService.selectUserVoById(id));
	}


	@GetMapping("/user-ids")
	@Inner(false)
	public List<SysUser> userByIs(@RequestParam("ids") List<Integer> ids) {
		return userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUserId,ids));
	}

	@GetMapping("/user-id")
	@Inner(false)
	public SysUser userById(@RequestParam("id") Integer id){
		return userService.getById(id);
	}

	@GetMapping("/user-username")
	@Inner(false)
	public SysUser userByUserName(@RequestParam("username") String username){
		return userService.getOne(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getUsername,username));
	}

	@GetMapping("/users-username")
	@Inner(false)
	List<SysUser> userByUserNames(@RequestParam("usernames") List<String> usernames){
		return userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getUsername,usernames));
	}

	/**
	 * 根据用户名查询用户信息
	 *
	 * @param username 用户名
	 * @return
	 */
	@GetMapping("/details/{username}")
	public R user(@PathVariable String username) {
		SysUser condition = new SysUser();
		condition.setUsername(username);
		return R.ok(userService.getOne(new QueryWrapper<>(condition)));
	}

	/**
	 * 根据条件查询用户信息
	 * @param user
	 * @return
	 */
	@Inner
	@GetMapping("/user-info")
	public R user(SysUser user) {
		user = userService.getOne(Wrappers.<SysUser>query(user));
		if (user == null) {
			return R.failed(null, String.format("用户信息为空 %s", user));
		}
		return R.ok(userService.findUserInfo(user));
	}

	/**
	 * 添加用户
	 *
	 * @param userDto 用户信息
	 * @return success/false
	 */
	@SysLog("添加用户")
	@PostMapping
	@PreAuthorize("@pms.hasPermission('sys_user_add')")
	public R user(@RequestBody UserDTO userDto) {
		if (userDto.getIsCorpWxEmp()) {
			if(!userDto.getUsername().equals(userDto.getPhone())) {
				throw new CheckedException("企业成员用户名与手机号必须一致");
			}
			//是企业微信成员，先在企业微信端创建
			Integer deptId = userDto.getDeptId();
			SysWxDeptRelation sysWxDeptRelation = relationService.getOne(Wrappers.<SysWxDeptRelation>lambdaQuery()
					.eq(SysWxDeptRelation::getSysDeptId, deptId));
			WxEmpDto dto = new WxEmpDto();
			dto.setUserid(userDto.getUsername());
			dto.setName(userDto.getName());
			dto.setMain_department(sysWxDeptRelation.getWxDeptId());
			dto.setMobile(userDto.getPhone());
			dto.setGender(userDto.getGender());
			R result = remoteWxService.createEmp(dto, SecurityConstants.FROM_IN);
			if(result != null && result.getCode()==0) {
				//系统成员添加
				return R.ok(userService.saveUser(userDto));
			}
		}else {
			return R.ok(userService.saveUser(userDto));
		}
		return R.failed(Boolean.FALSE);
	}

	/**
	 * 更新用户信息(系统信息编辑：角色、手机号、部门、状态)
	 *
	 * @param userDto 用户信息
	 * @return R
	 */
	@SysLog("更新用户信息")
	@PutMapping
	@PreAuthorize("@pms.hasPermission('sys_user_edit')")
	public R updateUser(@Valid @RequestBody UserRoleDTO userDto) {
		return R.ok(userService.updateUser(userDto));
		/*//查询原始用户信息
		SysUser sysUser = userService.getById(userDto.getUserId());
		//判断用户是否企业微信成员
		R<WxEmpVo> result = remoteWxService.getEmp(sysUser.getPhone(), SecurityConstants.FROM_IN);
		if (result != null && result.getCode()==0) {
			//优先更新企业微信成员
			WxEmpDto dto = new WxEmpDto();
			dto.setUserid(result.getData().getUserid());
			dto.setName(userDto.getName());
			dto.setGender(userDto.getGender());
			R rst = remoteWxService.updateEmp(dto, SecurityConstants.FROM_IN);
			if(rst != null && rst.getCode()==0) {
				//更新系统用户
				return R.ok(userService.updateUser(userDto));
			}
		}else {
			return R.ok(userService.updateUser(userDto));
		}
		return R.failed(Boolean.FALSE);*/
	}

	@SysLog("重置密码")
	@PutMapping("/resetPwd")
	@PreAuthorize("@pms.hasPermission('sys_user_reset')")
	public R resetPwd(Integer userId) {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
		return R.ok(userService.resetPwd(userId));
	}

	/**
	 * 删除用户信息
	 *
	 * @param id ID
	 * @return R
	 */
	@SysLog("删除用户信息")
	@DeleteMapping("/{id}")
	@PreAuthorize("@pms.hasPermission('sys_user_del')")
	@ApiOperation(value = "删除用户", notes = "根据ID删除用户")
	@ApiImplicitParam(name = "id", value = "用户ID", required = true, dataType = "int", paramType = "path")
	public R userDel(@PathVariable Integer id) {
		//判断用户是否企业微信成员
		SysUser sysUser = userService.getById(id);
		//优先删除企业成员
		R rst = remoteWxService.deleteEmp(sysUser.getUsername(),SecurityConstants.FROM_IN);
		if (rst != null && rst.getCode()==0) {
			return R.ok(userService.deleteUserById(sysUser));
		}
		return R.failed(Boolean.FALSE);
	}

	/**
	 * 分页查询用户
	 *
	 * @param page    参数集
	 * @param userDTO 查询参数列表
	 * @return 用户集合
	 */
	@GetMapping("/page")
	public R getUserPage(Page page, /*@Validated */UserDTO userDTO) {
		IPage userPage = null;
		Integer deptId = userDTO.getDeptId();
		if (deptId == null) {
			userPage = userService.getUsersWithRolePage(page, userDTO);
		} else {
			SysDept sysDept = sysDeptService.getById(deptId);
			Integer deptType = sysDept.getDeptType();
			if (deptType != UpmsConstant.DEPT_TYPE_ORGAN && deptType != UpmsConstant.DEPT_TYPE_LINE)
				return R.failed(Boolean.FALSE);
			if (deptType == UpmsConstant.DEPT_TYPE_ORGAN) {
				userPage = userService.getUsersWithRolePage(page, userDTO);
			} else {
				userPage = userService.getUsersWithLineDeptPage(page, userDTO);
			}
		}
		List<UserVO> users = new ArrayList<>();
		userPage.getRecords().forEach(obj -> {
			//企业成员信息查询
			UserVO userVo = (UserVO) obj;
			userVo.setIsCorpWxEmp(Boolean.FALSE);
			if (userVo.getPhone() != null) {
				R<WxEmpVo> result = remoteWxService.getEmp(userVo.getPhone(), SecurityConstants.FROM_IN);
				if(result != null && result.getCode()==0) {
					WxEmpVo wxEmpVo = result.getData();
					userVo.setIsCorpWxEmp(Boolean.TRUE);
					userVo.setGender(wxEmpVo.getGender());
//				userVo.setName(wxEmpVo.getName());
//				userVo.setUsername(userVo.getUsername());
				}
			}
			users.add(userVo);
		});
		Page<UserVO> voPage = new Page<>();
		BeanUtil.copyProperties(page,voPage,new String[]{"optimizeCountSql","records","orders"});
		voPage.setRecords(users);
		return R.ok(voPage);
	}

	@GetMapping("/list/{deptId}")
	public R list(@PathVariable("deptId") Integer deptId) {
		List<SysUser> users = userService.list(
				Wrappers.<SysUser>lambdaQuery()
				.eq(SysUser::getDeptId, deptId)
				.eq(SysUser::getDelFlag, 0)
				.ne(SysUser::getUserId, 1)
		);
		return R.ok(users);
	}

	/**
	 * 条线部门用户列表查询
	 *
	 * @param lineDeptId 条线部门id
	 * @return 用户集合
	 */
	@GetMapping("/getLineDeptUsers/{lineDeptId}")
	public R getLineDeptUsers(@PathVariable() Integer lineDeptId) {
		SysDept sysDept = sysDeptService.getById(lineDeptId);
		Integer deptType = sysDept.getDeptType();
		if (deptType == UpmsConstant.DEPT_TYPE_LINE)
			return R.ok(userService.getUsersWithLineDept(lineDeptId));
		return R.failed(Boolean.FALSE);
	}

	/**
	 * 修改个人信息(个人信息编辑：密码、头像)
	 *
	 * @param userDto userDto
	 * @return success/false
	 */
	@SysLog("修改个人信息")
	@PutMapping("/edit")
	public R updateUserInfo(@Valid @RequestBody UserDTO userDto) {
		return userService.updateUserInfo(userDto);
	}

	/**
	 * @param username 用户名称
	 * @return 上级部门用户列表
	 */
	@GetMapping("/ancestor/{username}")
	public R listAncestorUsers(@PathVariable String username) {
		return R.ok(userService.listAncestorUsers(username));
	}

	@Inner
	@GetMapping("/selectbyrole/{roleId}")
	public R selectByRole(@PathVariable Integer roleId) {
		List<Object> phones = userService.selectByRole(roleId);
		return R.ok(phones);
	}
	@Inner
	@GetMapping("/getrolename/{roleId}")
	public R getRoleName(@PathVariable Integer roleId) {
		String name = roleService.getObj(Wrappers.<SysRole>lambdaQuery().select(SysRole::getRoleName).eq(SysRole::getRoleId, roleId), o -> o.toString());
		return R.ok(name);
	}

	/**
	 * 企业微信初始化成员远程同步到系统用户
	 * @param param
	 */
	@Inner
	@PostMapping("/sync")
	public void onSyncWxEmp(@RequestBody Map<String,String> param) {
		if(param.isEmpty()) {
			return;
		}
		List<SysUser> users = JSONUtil.toBean(param.get("users"), new TypeReference<List<SysUser>>(){},false);
		userService.onSyncWxEmp(users);
	}

	@Inner(value = false)
	@PostMapping("/getUserPage")
	@ApiOperation(value = "按分页列表查询用户")
	public R getUserPage(@RequestParam(value = "name", required = false) String name, @RequestParam("deptId") Integer deptId, @RequestBody Page page) {
		SysDept sysDept = sysDeptService.getById(deptId);
		if (sysDept == null)
			return R.failed("部门不存在或已被删除");
		Integer deptType = sysDept.getDeptType();
		IPage users = userService.getUserPage(name, deptId, deptType, page);
		return R.ok(users);
	}


	@Inner(value = false)
	@PostMapping("/getUserPageByObjectId")
	@ApiOperation(value = "按分页列表查询用户")
	public R getUserPageByObjectId(@RequestParam(value = "name", required = false) String name, @RequestParam("deptId") Integer deptId, @RequestBody Page page,@RequestParam("objectId") Integer objectId) {
		SysDept sysDept = sysDeptService.getById(deptId);
		if (sysDept == null)
			return R.failed("部门不存在或已被删除");
		Integer deptType = sysDept.getDeptType();
		IPage users = userService.getUserPageByObjectId(name, deptId, deptType, page,objectId);
		return R.ok(users);
	}

	@Inner(value = false)
	@GetMapping("/users")
	public List<Map<String, Object>> users(@RequestParam(name = "userIds") List<Integer> userIds) {
		if (userIds == null || userIds.size() == 0) {
			return new ArrayList<>();
		}
		QueryWrapper wrapper = new QueryWrapper();
		wrapper.select("user_id as userId, name as userName");
		wrapper.in("user_id", userIds);
		wrapper.eq("del_flag", 0);
		return userService.listMaps(wrapper);
	}

	@Inner
	@GetMapping("/dept-ids")
	public List<SysUser> userByDeptIds(@RequestParam("ids") List<Integer> ids) {
		return userService.list(Wrappers.<SysUser>lambdaQuery().in(SysUser::getDeptId, ids));
	}
}
